package com.imooc.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author ：wangshuliang
 * @date ：Created in 2020/3/5 10:44 下午
 * @description：AOP切面Service时间调用统计类
 * @modified By：
 * @version: 1$
 */
@Aspect
@Component
public class ServiceLogAspect {
    public final static Logger LOGGER = LoggerFactory.getLogger(ServiceLogAspect.class);

    /**
     * AOP通知
     * 1、前置通知： 在方法调用之前通知
     * 2、后置通知： 在方法之后调用通知
     * 3、环绕通知： 在方法调用之前和之后，都可以分别执行的通知
     * 4、异常通知： 如果在方法调用过程中发生异常 则通知
     * 5、最终通知： 在方法调用之后通知
     */

    /**
     * 切面表达式
     * execution 代表所要执行的表达式主体
     * 第一处 * 代表方法返回类型 * 代表所有类型
     * 第二处 包名代表aop监控的类所在包
     * 第三处 .. 代表该包以及其子包下的所有类方法
     * 第四处 * 代表类名 * 代表所有类
     * 第五处 *(..)   * 代表类中的方法名，(..)表示方法中的仍何参数
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.imooc.service.impl..*.*(..))")
    public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
        LOGGER.info("====== 开始执行{}.{} ======",
                joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());
        // 记录开始时间
        long begin = System.currentTimeMillis();

        // 执行目标service
        Object result = joinPoint.proceed();

        // 记录结束时间
        long end = System.currentTimeMillis();

        long takeTime = end - begin;

        // 针对不同的时间 输出不同的日志级别
        if (takeTime > 3000){
            LOGGER.error("========= 执行结束，耗时:{} 毫秒 =======",takeTime);
        } else if ( takeTime >2000 ){
            LOGGER.warn("=======执行结束，耗时:{}毫秒 =========",takeTime);
        } else {
            LOGGER.info("=======执行结束，耗时:{}毫秒 =========",takeTime);
        }
        return result;
    }
}
